package test.demo.io;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author Hinsteny
 * @date 2016/5/26
 * @copyright: 2016 All rights reserved.
 */
public class AioServer {
	
	private final Integer port;

	public AioServer(int port) {
		this.port = port;
	}

	public void listen() {
		try {
			ExecutorService executorService = Executors.newCachedThreadPool();
			AsynchronousChannelGroup threadGroup = AsynchronousChannelGroup.withCachedThreadPool(executorService, 1);
			
			try (AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open(threadGroup)) {
				server.bind(new InetSocketAddress(port));
				
				System.out.println("Echo listen on:" + port);
				server.accept(null,
						new CompletionHandler<AsynchronousSocketChannel, Object>() {
							// 这里构造buffer是，用allocateDirect方法，下面打印客户端来的数据时会出错，why?
							final ByteBuffer echoBuffer = ByteBuffer.allocate(1024);

							public void completed(AsynchronousSocketChannel result, Object attachment) {
								System.out.println("Client data is coming ....");
								try {
									echoBuffer.clear();
									result.read(echoBuffer).get();
									// 打印从客户端接收到的数据
									System.out.println("Data is: " + new String(echoBuffer.array()));
									//清空buffer里面的缓存
									echoBuffer.flip();
									// 发送数据到客户端
									result.write(ByteBuffer.wrap("Welcome Hinsteny!".getBytes()));
									echoBuffer.flip();
								} catch (InterruptedException | ExecutionException e) {
									System.out.println(e.toString());
								} finally {
									try {
										result.close();
										server.accept(null, this);
									} catch (Exception e) {
										System.out.println(e.toString());
									}
								}
							}

							@Override
							public void failed(Throwable exc, Object attachment) {
								System.out.println("server failed: " + exc);
							}
						});

				try {
					// Wait for ever
					Thread.sleep(Integer.MAX_VALUE);
				} catch (InterruptedException ex) {
					System.out.println(ex);
				}
			}
		} catch (IOException e) {
			System.out.println(e);
		}
	}
	
    public static void main(String args[]) {
        new AioServer(8000).listen();
    }  
  
}
